<?php

namespace shop\components;

use backend\util\httpcurl\HttpCurl;
use Yii;
use yii\base\Component;

//use GuzzleHttp\Client;

class WeChat extends Component
{
    public $redis;

//    public $client;

    public $wxAppId;

    public $wxSecret;

    public $access_token;

    public $jsApiTicket;

    public $errorCode;

    public $error;

    public function __construct($appid, $secret)
    {
        parent::__construct();

        $this->redis = Yii::$app->redis;
//        $this->client = new Client();
        $this->wxAppId = $appid;
        $this->wxSecret = $secret;

        $this->access_token = null;
        $this->jsApiTicket = null;

        $this->error = '';
        $this->errorCode = '';

    }

    public function requestAccessToken()
    {
        $authName = 'wechat_access_token_' . $this->wxAppId;
        $expireKey = 'wechat_access_token_expire_' . $this->wxAppId;

        $expireValue = $this->redis->get($expireKey);

        if ($expireValue < time()) {
            $this->redis->del($authName);
            $this->redis->del($expireKey);

            $request = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $this->wxAppId . '&secret=' . $this->wxSecret;
//            $json_encode_str = $this->client->get($request);
//            $response = $this->client->get($request);
            $json_encode_str = HttpCurl::http_get($request);
            $json_decode_obj = json_decode($json_encode_str, true);

            $error = isset($json_decode_obj['errcode']) ? $json_decode_obj['errcode'] : false;
            $access_token = isset($json_decode_obj['access_token']) ? $json_decode_obj['access_token'] : '';
            if (!$error) {
                $expire = 6200;
                $this->redis->set($authName, $access_token);
                $this->redis->expire($authName, $expire);

                $this->redis->set($expireKey, time() + $expire);

                return $access_token;
            }

        } else {
            return $this->redis->get($authName);
        }
    }

    public function getSessionKey($code)
    {
        $res = array();
        if ($code) {
            $request = 'https://api.weixin.qq.com/sns/jscode2session?appid=' . $this->wxAppId . '&secret=' . $this->wxSecret . '&js_code=' . $code . '&grant_type=authorization_code';
            $json_encode_str = HttpCurl::http_get($request);
            $res = json_decode($json_encode_str, true);
            //file_put_contents('./wx.log', $json_encode_str, FILE_APPEND);
        }
        return $res;
    }

    public function wxLogin($code)
    {
        $session_key_item = $this->getSessionKey($code);

        if ($session_key_item) {
            $error = isset($session_key_item['errcode']) ? $session_key_item['errcode'] : false;
            if ($error) {
                $rs = array('result' => false, 'desc' => $session_key_item['errmsg']);
            } else {
                $expires_in = isset($session_key_item['expires_in']) ? $session_key_item['expires_in'] : null;
                $openid = $session_key_item['openid'];
                $session_key = $session_key_item['session_key'];

                $access_token = $this->requestAccessToken();

                $json_data = array('openid' => $openid, 'access_token' => $access_token, 'expires_in' => $expires_in, 'session_key' => $session_key);

                if ($session_key && !isset($session_key_item['errcode'])) {
                    $json_data['unionid'] = isset($session_key_item['unionid']) ? $session_key_item['unionid'] : '';
                    $session_key_item['errmsg'] = '成功';
                } else {
                    $json_data['errcode'] = isset($session_key_item['errcode']) ? $session_key_item['errcode'] : '';
                    $json_data['errmsg'] = isset($session_key_item['errmsg']) ? $session_key_item['errmsg'] : '';

                }

                $rs = array('result' => true, 'desc' => $session_key_item['errmsg'], 'data' => $json_data);
            }
        } else {
            $rs = array('result' => false, 'desc' => '错误');
        }
        return $rs;
    }

    public function getDecryptData($sessionKey, $iv, $encryptedData)
    {
        if (strlen($sessionKey) != 24) {
            $rs = array('result' => false, 'desc' => 'session不对');
        } else if (strlen($iv) != 24) {
            $rs = array('result' => false, 'desc' => 'iv不对');
        } else {
            $aesKey = base64_decode($sessionKey);
            $aesIV = base64_decode($iv);

            $aesCipher = base64_decode($encryptedData);
            $decrypt_result = openssl_decrypt($aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);

            $data = json_decode($decrypt_result, true);
            if ($data) {
                if ($data['watermark']['appid'] != $this->wxAppId) {
                    $rs = array('result' => false, 'desc' => 'appid返回错误');

                } else {
                    $rs = array('result' => true, 'desc' => '成功', 'data' => $data);
                }
            } else {
                $rs = array('result' => false, 'desc' => '结果为空');
            }
        }

        return $rs;
    }

    /**
     * 获取JSAPI授权TICKET
     */
    public function getJsTicket()
    {
        $access_token = $this->requestAccessToken();
        if (!$access_token) return false;

        $authName = 'wechat_jsapi_ticket_' . $this->wxAppId;
        $rs = $this->redis->get($authName);

        if ($rs) {
            $this->jsApiTicket = $rs;
            return $rs;
        }

        $request = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' . $access_token . '&type=jsapi';
        $json_encode_str = Httpcurl::http_get($request);
        $json_decode_obj = json_decode($json_encode_str, true);

        if ($json_decode_obj) {

            $error = $json_decode_obj['errcode'];
            if (!$error) {
                $expire = $json_decode_obj['expires_in'] ? intval($json_decode_obj['expires_in']) - 100 : 3600;
                $this->jsApiTicket = $json_decode_obj['ticket'];
                $this->redis->set($authName, $this->jsApiTicket);
                $this->redis->expire($authName, $expire);
            } else {
                $this->errorCode = $error;
                $this->error = $json_decode_obj['errmsg'];
            }

            return $this->jsApiTicket;
        }
        return false;
    }

    public function getJsSign($url)
    {
        if (!$this->jsApiTicket && !$this->getJsTicket() || !$url) return false;
        $timestamp = time();
        $noncestr = $this->generateNonceStr();

        $ret = strpos($url, '#');
        if ($ret) {
            $url = substr($url, 0, $ret);
        }
        $url = trim($url);
        if (empty($url))
            return false;
        $arrData = array("timestamp" => $timestamp, "noncestr" => $noncestr, "url" => $url, "jsapi_ticket" => $this->jsApiTicket);
        $sign = $this->getSignature($arrData);
        if (!$sign) {
            return false;
        }
        $signPackage = array(
            "appid" => $this->wxAppId,
            "noncestr" => $noncestr,
            "timestamp" => $timestamp,
            "url" => $url,
            "signature" => $sign
        );
        return $signPackage;
    }

    public function generateNonceStr($length = 16)
    {
        // 密码字符集，可任意添加你需要的字符
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= $chars[mt_rand(0, strlen($chars) - 1)];
        }
        return $str;
    }

    public function getSignature($arrData, $method = "sha1")
    {
        if (!function_exists($method)) return false;
        ksort($arrData);
        $paramString = "";
        foreach ($arrData as $key => $value) {
            if (strlen($paramString) == 0)
                $paramString .= $key . "=" . $value;
            else
                $paramString .= "&" . $key . "=" . $value;
        }
        $Sign = $method($paramString);
        return $Sign;
    }

    /**
     * 小程序消息
     * @param $msg
     * @return mixed
     */
    public function sendMsg($msg)
    {
        $this->access_token = $this->requestAccessToken();
        $url = 'https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=' . $this->access_token;
        $str = json_encode((object)$msg);
        $result = HttpCurl::http_post($url, $str);
        $arr_json = json_decode($result, true);
        return $arr_json;
    }

    /**
     * 统一服务消息 一般发送到公众号
     * @param $msg
     * @return mixed
     */
    public function sendMsgSome($msg)
    {
        $this->access_token = $this->requestAccessToken();
        $url = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token=" . $this->access_token;
        $str = json_encode((object)$msg);
        $result = Httpcurl::http_post($url, $str);
        $arr_json = json_decode($result, true);
        return $arr_json;
    }

    public function qrCode($dir, $scene, $page, $width=430)
    {
        $path = dirname(dirname(dirname(__FILE__))) . '/' . $dir . '/';
        $file_hash = md5($scene);
        $file_name = $file_hash . '.jpg';
        @mkdir($path, 0755, true);
        $access_token = $this->requestAccessToken();
        if (!$access_token) {
            return false;
        }

        $url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" . $access_token;
        $data = array(
            'page' => $page,
            'scene' => $scene,
            'width' => $width,
        );
        $data_str = json_encode($data);
        $result = HttpCurl::http_post($url, $data_str);
        $error = json_decode($result, true);
        if (!$error) {
            $flag = file_put_contents($path . $file_name, $result);
            if ($flag) {
                return $file_name;
            }
        } else {
            return $error;
        }
    }
}